package com.roamer.javase.demo.export.vo;

import lombok.Data;
import lombok.EqualsAndHashCode;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 多部分数据 pro
 *
 * @author roamer
 * @version v1.0
 * @date 2020/5/5 17:25
 */
@EqualsAndHashCode(callSuper = true)
@Data
public class MultipartProModel extends ExportModel {
    private static final long serialVersionUID = -2799134454672708920L;

    private List<ExportModel> exportModels;

    public MultipartProModel(List<ExportModel> exportModels) {
        assert exportModels != null && !exportModels.isEmpty();
        this.exportModels = exportModels;
    }

    @Override
    public List<Map<String, Object>> getDataMapList() {
        List<List<Map<String, Object>>> allList = exportModels.stream().map(ExportModel::getDataMapList).collect(Collectors.toList());
        int max = allList.stream().mapToInt(List::size).max().getAsInt();
        List<Map<String, Object>> mergeDataMapList = new ArrayList<>(max);

        // 合并结果集
        for (int i = 0; i < max; i++) {
            Map<String, Object> dataMap = null;
            for (int j = 0; j < allList.size(); j++) {
                List<Map<String, Object>> dataMapList = allList.get(j);
                // 第一个模组，并且没有超出自身记录，则进行初始化
                if (j == 0 && i < dataMapList.size()) {
                    dataMap = new LinkedHashMap<>(dataMapList.get(i));
                    continue;
                }
                // 获取已经存在的记录
                dataMap = Optional.ofNullable(dataMap).orElseGet(LinkedHashMap::new);
                // 除了第一个模组，其他模组插入数据前，先插入分割列数据
                if (j != 0) {
                    dataMap.put("_" + j, "");
                }
                // 溢出补空
                if (i >= dataMapList.size()) {
                    Map<String, Object> finalDataMap = dataMap;
                    int finalJ1 = j;
                    exportModels.get(j).getExportHeaderAlias().forEach((k, v) -> finalDataMap.put(k + "_" + finalJ1, ""));
                    continue;
                }
                Map<String, Object> finalDataMap = dataMap;
                int finalJ = j;
                dataMapList.get(i).forEach((k, v) -> finalDataMap.put(k + "_" + finalJ, v));
            }
            mergeDataMapList.add(dataMap);
        }
        return mergeDataMapList;
    }

    @Override
    public List<int[]> getMergedRegion() {
        List<int[]> list = new ArrayList<>();
        // 寻找最大的记录结束行
        int max = exportModels.stream().flatMap(exportModel -> exportModel.getMergedRegion().stream()).mapToInt(ints -> ints[1]).max().getAsInt();
        int offset = 0;
        for (int i = 0; i < exportModels.size(); i++) {
            ExportModel exportModel = exportModels.get(i);
            // 空白列
            if (i > 0) {
                // 无数据时，空白列会多1行的处理
                if (max == 2) {
                    list.add(new int[]{1, 1, offset, offset});
                } else {
                    list.add(new int[]{1, max, offset, offset});
                }
                offset++;
            }
            for (int j = 0; j < exportModel.getMergedRegion().size(); j++) {
                int[] regions = exportModel.getMergedRegion().get(j);
                list.add(new int[]{regions[0], max, regions[2] + offset, regions[3] + offset});
            }
            offset += exportModel.getExportHeaderAlias().size();
        }
        return list;
    }

    @Override
    public String getExportTitle() {
        return exportModels.size() > 1 ? exportModels.get(0).getExportTitle() + "对比" : exportModels.get(0).getExportTitle();
    }

    @Override
    public Map<String, String> getExportHeaderAlias() {
        // 合并结果集
        Map<String, String> headerAlias = new LinkedHashMap<>(exportModels.get(0).getExportHeaderAlias());
        for (int i = 1; i < exportModels.size(); i++) {
            // 分割列
            headerAlias.put("_" + i, String.join("", Collections.nCopies(i, " ")));
            int finalI = i;
            exportModels.get(i).getExportHeaderAlias().forEach((k, v) -> headerAlias.put(k + "_" + finalI, v + String.join("", Collections.nCopies(finalI, " "))));
        }
        return headerAlias;
    }
}
